package com.ccp.dev.workflow.controller;

import com.ccp.dev.core.basic.annotion.Action;
import com.ccp.dev.core.basic.annotion.ActionExecOrder;
import com.ccp.dev.core.basic.consts.UrlConstants;
import com.ccp.dev.core.basic.internationalization.SysBaseController;
import com.ccp.dev.core.basic.model.SysAuditModelType;
import com.ccp.dev.core.basic.response.ResultData;
import com.ccp.dev.core.basic.util.UUIDUtils;
import com.ccp.dev.core.util.*;
import com.ccp.dev.core.util.log.SysAuditThreadLocalHolder;
import com.ccp.dev.workflow.model.*;
import com.ccp.dev.workflow.service.ActDefModelService;
import com.ccp.dev.workflow.service.BpmNodeButtonService;
import com.ccp.dev.workflow.service.BpmNodeSetService;
import net.sf.json.JSONArray;
import org.dom4j.Document;
import org.dom4j.Element;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * ClassDescribe:
 * 对象功能:自定义工具条 控制器类
 *
 * @author :wangcheng
 * Date: 2019-06-17
 */
@RequestMapping(UrlConstants.PROJECT_ROOT + UrlConstants.PROJECT_MODULE_WORKFLOW + "/bpmNodeButton")
@Controller
@Action(ownermodel = SysAuditModelType.PROCESS_MANAGEMENT)
public class BpmNodeButtonController extends SysBaseController {

    @Resource
    private BpmNodeButtonService bpmNodeButtonService;
    @Resource
    private ActDefModelService actDefModelService;
    @Resource
    private BpmNodeSetService bpmNodeSetService;

    /**
     * 操作按钮列表界面 list
     *
     * @param model   流程模型
     * @param request http请求
     * @return 操作按钮列表页面
     * @throws Exception 异常
     */
    @RequestMapping(UrlConstants.VIEW_DISPATCH_PREFIX + UrlConstants.MODULE_FUNCTION_LIST)
    @Action(description = "操作按钮列表界面", detail = "操作按钮列表界面")
    public String list(Model model, HttpServletRequest request) throws Exception {
        String modelId = RequestUtil.getString(request, "modelId");

        //根据modelId获取流程模型定义ID（procDefId）
        ActDefModel actDefModel = actDefModelService.getOneById(modelId);
        String procDefId = actDefModel.getProcDefId();
        List<BpmNodeSet> bpmNodeSets = bpmNodeSetService.queryByProcDefId(procDefId);

        Map<String, FlowNodeInfo> taskNodeMap = NodeCache.getByProcDefId(procDefId);
        Map<String, List<BpmNodeButton>> nodeButtonMap = bpmNodeButtonService.getMapByProcDefId(procDefId);
        Map<String, List<BpmButton>> initButtonMap = new HashMap<>(16);

        // 读button.xml
        String buttonPath = StringPool.SLASH + StringPool.BUTTON_FILE;
        String xml = FileUtil.readFile(buttonPath);
        Document document = Dom4jUtil.loadXml(xml);
        Element root = document.getRootElement();
        String xmlStr = root.asXML();
        BpmNodeButtonXml bpmButtonList = (BpmNodeButtonXml) XmlBeanUtil.unmarshall(xmlStr, BpmNodeButtonXml.class);
        List<BpmButton> buttons = bpmButtonList.getButtons();

        // 对按钮进行分类
        //起始节点按钮
        List<BpmButton> startBtnList = new ArrayList<>();
        //第一个节点按钮
        List<BpmButton> firstNodeBtnList = new ArrayList<>();
        //会签节点按钮
        List<BpmButton> signBtnList = new ArrayList<>();
        //普通节点按钮
        List<BpmButton> commonBtnList = new ArrayList<>();
        for (BpmButton button : buttons) {
            if (button.getInit() == 0) {
                continue;
            }

            Integer btnType = button.getType();

            switch (btnType) {
                case 0:
                    startBtnList.add(button);
                    break;
                case 1:
                    firstNodeBtnList.add(button);
                    break;
                case 2:
                    signBtnList.add(button);
                    break;
                case 3:
                    commonBtnList.add(button);
                    break;
                case 4:
                    signBtnList.add(button);
                    commonBtnList.add(button);
                    break;
                default:
                    break;
            }
        }

        for (FlowNodeInfo nodeInfo : taskNodeMap.values()) {
            String nodeId = nodeInfo.getNodeId();
            if (!nodeButtonMap.containsKey(nodeId)) {
                if ("startEvent1".equals(nodeId)) {
                    initButtonMap.put(nodeId, startBtnList);
                    continue;
                }

                if (nodeInfo.getIsSignNode()) {
                    initButtonMap.put(nodeId, signBtnList);
                    continue;
                }

                if (nodeInfo.getIsFirstNode()) {
                    initButtonMap.put(nodeId, firstNodeBtnList);
                    continue;
                }

                initButtonMap.put(nodeId, commonBtnList);
            }

        }

        //重定向跳转实现页面刷新，带有返回信息
        String isReturn = RequestUtil.getString(request, "isReturn");
        if (StringUtil.isNotEmpty(isReturn)) {
            model.addAttribute("isReturn", isReturn);
        }
        model.addAttribute("nodeButtonMap", nodeButtonMap);
        model.addAttribute("taskNodeMap", taskNodeMap);
        model.addAttribute("bpmNodeSetList", bpmNodeSets);
        model.addAttribute("actDefModel", actDefModel);
        model.addAttribute("initButtonMap", initButtonMap);
        return getAutoView();
    }

    /**
     * 初始化所有的操作按钮
     *
     * @param request http请求
     * @return 跳转路径
     */
    @RequestMapping(UrlConstants.VIEW_DISPATCH_PREFIX + "/initAll")
    @Action(description = "初始化所有的操作按钮",
            detail = "初始化流程定义 【${modelId}】的全部操作按钮<#if success>成功<#else>失败</#if>")
    public String initAll(HttpServletRequest request) {
        String modelId = RequestUtil.getString(request, "modelId");
        SysAuditThreadLocalHolder.putParamerter("modelId", modelId);
        try {
            bpmNodeButtonService.initAll(modelId);
            SysAuditThreadLocalHolder.putParamerter("success", true);
            return "redirect:list?modelId=" + modelId + "&isReturn=true";
        } catch (Exception e) {
            e.printStackTrace();
            SysAuditThreadLocalHolder.putParamerter("success", false);
            return "redirect:list?modelId=" + modelId + "&isReturn=false";
        }
    }

    /**
     * 初始化某节点的操作按钮
     *
     * @param request http请求
     * @return 跳转路径
     */
    @RequestMapping(UrlConstants.VIEW_DISPATCH_PREFIX + "/init")
    @Action(description = "初始化某节点的操作按钮", detail = "初始化某节点的操作按钮")
    public String init(HttpServletRequest request) {
        String modelId = RequestUtil.getString(request, "modelId");
        String nodeId = RequestUtil.getString(request, "nodeId");
        String isEdit = RequestUtil.getString(request, "isEdit");

        //判断跳转路径
        String urlStr;
        if (StringUtil.isNotEmpty(isEdit)) {
            urlStr = "redirect:getByNode?modelId=" + modelId + "&nodeId=" + nodeId;
        } else {
            urlStr = "redirect:list?modelId=" + modelId;
        }

        try {
            bpmNodeButtonService.init(modelId, nodeId);
            return urlStr + "&isReturn=true";
        } catch (Exception e) {
            return urlStr + "&isReturn=false";
        }
    }

    /**
     * 清除按钮配置
     *
     * @param request http请求
     * @return 重定向页面
     */
    @RequestMapping(UrlConstants.VIEW_DISPATCH_PREFIX + "/delByDefId")
    @Action(description = "操作按钮清除按钮配置", execOrder = ActionExecOrder.BEFORE,
            detail = "清除流程定义 【${modelId}】的表单按钮<#if success>成功<#else>失败</#if>")
    public String delByDefId(HttpServletRequest request) {
        String modelId = RequestUtil.getString(request, "modelId");
        SysAuditThreadLocalHolder.putParamerter("modelId", modelId);

        try {
            bpmNodeButtonService.delByDefId(modelId);
            SysAuditThreadLocalHolder.putParamerter("success", true);
            return "redirect:list?modelId=" + modelId + "&isReturn=true";
        } catch (Exception e) {
            e.printStackTrace();
            SysAuditThreadLocalHolder.putParamerter("success", false);
            return "redirect:list?modelId=" + modelId + "&isReturn=false";
        }

    }

    /**
     * 删除按钮接口
     *
     * @param request http请求
     * @return 重定向页面
     */
    @RequestMapping(UrlConstants.VIEW_DISPATCH_PREFIX + "/deByDefNodeId")
    @Action(description = "操作按钮删除按钮接口", execOrder = ActionExecOrder.BEFORE,
            detail = "删除流程定义 【${modelId}】的节点的按钮操作<#if success>成功<#else>失败</#if>")
    public String deByDefNodeId(HttpServletRequest request) {
        String modelId = RequestUtil.getString(request, "modelId");
        String nodeId = RequestUtil.getString(request, "nodeId");
        String isEdit = RequestUtil.getString(request, "isEdit");
        SysAuditThreadLocalHolder.putParamerter("modelId", modelId);

        //判断跳转路径
        String urlStr;
        if (StringUtil.isNotEmpty(isEdit)) {
            urlStr = "redirect:getByNode?modelId=" + modelId + "&&nodeId=" + nodeId;
        } else {
            urlStr = "redirect:list?modelId=" + modelId;
        }

        try {
            bpmNodeButtonService.deByDefNodeId(modelId, nodeId);
            SysAuditThreadLocalHolder.putParamerter("success", true);
            return urlStr + "&isReturn=true";
        } catch (Exception e) {
            e.printStackTrace();
            SysAuditThreadLocalHolder.putParamerter("success", false);
            return urlStr + "&isReturn=false";
        }
    }

    /**
     * 编辑按钮接口
     *
     * @param request http请求
     * @return 跳转路径
     */
    @RequestMapping(UrlConstants.VIEW_DISPATCH_PREFIX + "/getByNode")
    @Action(description = "操作按钮编辑按钮接口", detail = "操作按钮编辑按钮接口")
    public String viewGetByNode(HttpServletRequest request, Model model) {
        Boolean buttonFlag = RequestUtil.getBoolean(request, "buttonFlag", true);
        String modelId = RequestUtil.getString(request, "modelId");
        String nodeId = RequestUtil.getString(request, "nodeId");
        String isReturn = RequestUtil.getString(request, "isReturn");
        if (StringUtil.isNotEmpty(isReturn)) {
            model.addAttribute("isReturn", isReturn);
        }
        //判断节点是否为空
        if (StringUtil.isEmpty(nodeId)) {
            model.addAttribute("isStartForm", 1);
        } else {
            model.addAttribute("isStartForm", 0);
        }
        model.addAttribute("modelId", modelId)
                .addAttribute("nodeId", nodeId)
                .addAttribute("buttonFlag", buttonFlag);
        return getAutoView();
    }

    /**
     * 获取操作按钮节点按钮列表数据
     * @param request http请求
     * @return 节点按钮列表
     */
    @RequestMapping("/getByNode")
    @Action(description = "操作按钮节点按钮列表数据", detail = "操作按钮节点按钮列表数据")
    @ResponseBody
    public ResultData getByNode(HttpServletRequest request) {
        String modelId = RequestUtil.getString(request, "modelId");
        String nodeId = RequestUtil.getString(request, "nodeId");
        //判断流程定义ID（modelId）是否为空
        if (StringUtil.isEmpty(modelId)) {
            return getResultDataError("没有输入流程定义ID");
        }
        //获取modelId对应的流程模型数据
        ActDefModel actDefModel = actDefModelService.getOneById(modelId);
        //判断节点是否为空
        List<BpmNodeButton> btnList;
        if (StringUtil.isEmpty(nodeId)) {
            btnList = bpmNodeButtonService.getByStartForm(actDefModel.getProcDefId());
        } else {
            btnList = bpmNodeButtonService.getByDefNodeId(actDefModel.getProcDefId(), nodeId);
        }
        return getResultDataSuccess("query.success", btnList);
    }

    /**
     * 操作按钮  编辑弹窗、添加弹窗
     *
     * @return 跳转路径
     */
    @RequestMapping(UrlConstants.VIEW_DISPATCH_PREFIX + "/edit")
    @Action(description = "操作按钮  编辑弹窗、添加弹窗", detail = "编辑自定义工具条<#if success>成功<#else>失败</#if>")
    public String viewEditNodeButton(HttpServletRequest request, Model model) throws Exception {
        String id = RequestUtil.getString(request, "id");
        String modelId = RequestUtil.getString(request, "modelId");
        String nodeId = RequestUtil.getString(request, "nodeId");
        Boolean buttonFlag = RequestUtil.getBoolean(request, "buttonFlag", true);

        BpmNodeButton bpmNodeButton;

        //根据modelId获取流程模型定义ID（procDefId）
        ActDefModel actDefModel = actDefModelService.getOneById(modelId);
        String procDefId = actDefModel.getProcDefId();
        model.addAttribute("actDefModel", actDefModel);

        if (StringUtil.isNotEmpty(id)) {
            //编辑弹窗
            bpmNodeButton = bpmNodeButtonService.getOneById(id);
        } else {
            //添加弹窗
            bpmNodeButton = new BpmNodeButton();
            bpmNodeButton.setProcDefId(procDefId);
            bpmNodeButton.setModelId(modelId);
            bpmNodeButton.setNodeid(nodeId);
            if (StringUtil.isNotEmpty(nodeId)) {
                //判断会签节点
                boolean rtn = NodeCache.isSignTaskNode(procDefId, nodeId);
                bpmNodeButton.setNodetype(rtn ? 1 : 0);
                bpmNodeButton.setIsstartform(0);
            } else {
                bpmNodeButton.setIsstartform(1);
            }
        }

        if(bpmNodeButton!=null){
            SysAuditThreadLocalHolder.putParamerter("success", true);
        }else{
            SysAuditThreadLocalHolder.putParamerter("success", false);
        }

        //读取按钮配置 button.xml
        String buttonPath = StringPool.SLASH + StringPool.BUTTON_FILE;
        String xml = FileUtil.readFile(buttonPath);
        Document document = Dom4jUtil.loadXml(xml);
        Element root = document.getRootElement();
        String xmlStr = root.asXML();
        BpmNodeButtonXml bpmButtonList = (BpmNodeButtonXml) XmlBeanUtil.unmarshall(xmlStr, BpmNodeButtonXml.class);
        List<BpmButton> buttons = bpmButtonList.getButtons();
        JSONArray array = JSONArray.fromObject(buttons);
        String buttonStr = array.toString();

        model.addAttribute("bpmNodeButton", bpmNodeButton)
                .addAttribute("procDefId", procDefId)
                .addAttribute("nodeId", nodeId)
                .addAttribute("buttonFlag", buttonFlag)
                .addAttribute("buttonStr", buttonStr);
        return getAutoView();

    }


    /**
     * 编辑页面    保存排序
     *
     * @param request http请求
     */
    @RequestMapping(UrlConstants.VIEW_DISPATCH_PREFIX + "/sort")
    @Action(description = "操作按钮编辑页面 保存排序", detail = "操作按钮编辑页面 保存排序<#if success>成功<#else>失败</#if>")
    @ResponseBody
    public ResultData sort(HttpServletRequest request) {
        String[] ids = RequestUtil.getStringAryByStr(request, "ids");
        //判断操作类型是否为空
        if (StringUtil.isEmpty(ids)) {
            SysAuditThreadLocalHolder.putParamerter("success", false);
            return getResultDataError("save.failure");
        }
        try {
            bpmNodeButtonService.sort(ids);
            SysAuditThreadLocalHolder.putParamerter("success", true);
            return getResultDataSuccess("save.success");
        } catch (Exception e) {
            e.printStackTrace();
            SysAuditThreadLocalHolder.putParamerter("success", false);
            return getResultDataError("save.failure", 1, e.getMessage());
        }
    }

    /**
     * 编辑页面     删除某个按钮
     *
     * @param request http请求
     * @return 重定向页面
     */
    @RequestMapping(UrlConstants.VIEW_DISPATCH_PREFIX + "/del")
    @Action(description = "操作按钮编辑页面 删除某个按钮", execOrder = ActionExecOrder.BEFORE,
            detail =  "删除流程定义【${modeId}】的节点:【${nodeId}】的自定义工具按钮:【${button.btnname}】 " +
                    "<#if success>成功<#else>失败</#if>")
    public String del(HttpServletRequest request) {
        String id = RequestUtil.getString(request, "id");
        String modelId = RequestUtil.getString(request, "modelId");
        String nodeId = RequestUtil.getString(request, "nodeId");
        BpmNodeButton button = bpmNodeButtonService.getOneById(id);

        SysAuditThreadLocalHolder.putParamerter("modelId", modelId);
        SysAuditThreadLocalHolder.putParamerter("nodeId", nodeId);
        SysAuditThreadLocalHolder.putParamerter("button", button);
        try {
            bpmNodeButtonService.delById(id);
            SysAuditThreadLocalHolder.putParamerter("success", true);
            return "redirect:getByNode?modelId=" + modelId + "&&nodeId=" + nodeId + "&isReturn=true";
        } catch (Exception e) {
            e.printStackTrace();
            SysAuditThreadLocalHolder.putParamerter("success", false);
            return "redirect:getByNode?modelId=" + modelId + "&&nodeId=" + nodeId + "&isReturn=false";
        }

    }

    /**
     * 弹窗 添加或更新按钮
     *
     * @param bpmNodeButton 添加或更新的实体
     * @return 操作封装结果集合
     */
    @RequestMapping(UrlConstants.VIEW_DISPATCH_PREFIX + "/form")
    @Action(description = "操作按钮 添加或更新按钮弹窗", detail = "操作按钮 添加或更新按钮弹窗")
    @ResponseBody
    public ResultData form(@RequestBody BpmNodeButton bpmNodeButton) {
        //根据ID的有无，判断是编辑弹窗还是新增弹窗
        if (bpmNodeButton.getId() == null || StringUtil.isEmpty(bpmNodeButton.getId())) {
            boolean rtn = bpmNodeButtonService.isOperatorExist(bpmNodeButton);
            if (rtn) {
                return getResultDataError("btn.operatorType.failure");
            }
            bpmNodeButton.setId(UUIDUtils.getUUIDFor32());
            bpmNodeButton.setSn(bpmNodeButton.getOperatortype().longValue());
            bpmNodeButtonService.add(bpmNodeButton);
            return getResultDataSuccess("operation.success");
        } else {
            boolean rtn = bpmNodeButtonService.isOperatorExistForUpd(bpmNodeButton);
            if (rtn) {
                return getResultDataError("btn.operatorType.failure");
            }
            bpmNodeButtonService.update(bpmNodeButton);
            return getResultDataSuccess("update.success");
        }
    }
}
